#ifndef __SPLINER2_HPP__
#define __SPLINER2_HPP__

#include <vector>
#include <cmath>
#include "macros.hpp"
#include "Spline.hpp"
#include "Parametrization.hpp"

class SplineR2
{

public:
	SplineR2( const std::vector<Spline::Point>& control_points, const Parametrization& parametrization );
	~SplineR2();

	// evalúa la curva con el t dado
	Spline::Point eval( double t ) const;
	Spline::Point operator() ( double t ) const;

	// devuelve el t del punto más cercano del spline
	double nearest( const Spline::Point& p ) const;

	// mueve el punto con el t dado a la posición dada
	void movePoint( double t, const Spline::Point& to );

	// devuelve la derivada en x e y del spline
	Spline::Point derivative( double t ) const;

	// devuelve la derivada 2da en x e y del spline
	Spline::Point derivative2( double t ) const;

	std::vector<Spline::Point> sample( uint samples ) const;
	std::ostream& print( std::ostream& out ) const;

private:
	void calc();
	double zeroWithBisection( const Spline::Point& point, double lbound, double rbound ) const;
	double zeroWithNewton( const Spline::Point& point, double t ) const;
	double nearest_point( const Spline::Point& p, uint i, double& min_dist ) const;
	double distance( const Spline::Point& point, double t, bool squared = false ) const;
	double distanceDerivative( const Spline::Point& point, double t ) const;

	std::vector<Spline::Point> _cp_x, _cp_y;
	Spline* _sx;
	Spline* _sy;

};

std::ostream& operator<<( std::ostream& out, const SplineR2& s );

#endif

